package org.mapdroid.maps.gmaps;

import java.io.IOException;

import org.mapdroid.R;
import org.mapdroid.maps.IMap;
import org.mapdroid.search.SearchAddressView;
import org.mapdroid.utils.SoundManager;
import org.mapdroid.utils.SoundManagerCostants;

import android.content.Context;
import android.content.Intent;
import android.graphics.Point;
import android.location.Location;
import android.location.LocationManager;
import android.net.Uri;
import android.os.Vibrator;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.GestureDetector.OnDoubleTapListener;
import android.view.GestureDetector.OnGestureListener;
import android.widget.Toast;

import com.google.android.maps.GeoPoint;
import com.google.android.maps.MapView;

public class MdMapView extends MapView implements IMap, OnGestureListener, OnDoubleTapListener{
	public static final int MAP_MODE_ID						= 0;
	public static final int SATELLITE_MODE_ID				= 1;
	public static final int STREET_VIEW_MODE_ID				= 2;
	public static final int TRAFFIC_MODE_ID					= 3;
	
	
	public static final int RANGE_OVERLAY_INDEX				= 1;
	
	public static final int SEARCH_ADDRESS_OVERLAY_INDEX 	= 2;
	public static final int SEARCH_PARKING_OVERLAY_INDEX	= 3;
	public static final int SEARCH_SERVICE_OVERLAY_INDEX	= 4;
	
	public static final int PARKING_OVERLAY_INDEX			= 5;
	public static final int RESTAURANT_OVERLAY_INDEX		= 6;
	public static final int BEAUTY_CENTER_OVERLAY_INDEX		= 7;
	public static final int CLOTHING_OVERLAY_INDEX			= 8;
	public static final int GYM_OVERLAY_INDEX				= 9;
	
	public static final int DRIVING_DIRECTIONS_OVERLAY_INDEX= 10;
	
	private SoundManager soundManager;
	private GestureDetector gestureDetector;
	private Context context;
	private boolean eventHandled;
	private int lastMarkerTapped;
	private int lastOverlayTapped;
	
	public MdMapView(Context context, String apiKey) {
		super(context, apiKey);
		// TODO Auto-generated constructor stub
		this.context = context;
		gestureDetector = new GestureDetector(context, this);
		eventHandled = false;
		
		soundManager = new SoundManager(context);
        soundManager.initSound(SoundManagerCostants.ZOOM_LIMIT_REACHED, R.raw.beep);
	}

	@Override
	public void animateTo(GeoPoint point) {
		// TODO Auto-generated method stub
		getController().animateTo(point);
	}

	@Override
	public void animateTo(Location location) {
		// TODO Auto-generated method stub
		GeoPoint point = new GeoPoint((int)(location.getLatitude()*1E6), (int)(location.getLongitude()*1E6));
		getController().animateTo(point);
	}

	@Override
	public MapView getMapView() {
		// TODO Auto-generated method stub
		return this;
	}

	@Override
	public View getView() {
		// TODO Auto-generated method stub
		return null;
	}
	
	public void hasEventHandled(boolean value){
		this.eventHandled = value;
	}
	
	@Override
	public void moveUp(){
		GeoPoint centerGeoPoint = getMapCenter();
		Point centerPoint = new Point();
		getProjection().toPixels(centerGeoPoint, centerPoint);
		GeoPoint newCenterGeoPoint = getProjection().fromPixels(centerPoint.x, centerPoint.y - getHeight()/4);
		animateTo(newCenterGeoPoint);
	}

	@Override
	public void moveDown(){
		GeoPoint centerGeoPoint = getMapCenter();
		Point centerPoint = new Point();
		getProjection().toPixels(centerGeoPoint, centerPoint);
		GeoPoint newCenterGeoPoint = getProjection().fromPixels(centerPoint.x, centerPoint.y + getHeight()/4);
		animateTo(newCenterGeoPoint);
	}
	
	@Override
	public void moveLeft(){
		GeoPoint centerGeoPoint = getMapCenter();
		Point centerPoint = new Point();
		getProjection().toPixels(centerGeoPoint, centerPoint);
		GeoPoint newCenterGeoPoint = getProjection().fromPixels(centerPoint.x - getWidth()/4, centerPoint.y);
		animateTo(newCenterGeoPoint);
	}
	
	@Override
	public void moveRight(){
		GeoPoint centerGeoPoint = getMapCenter();
		Point centerPoint = new Point();
		getProjection().toPixels(centerGeoPoint, centerPoint);
		GeoPoint newCenterGeoPoint = getProjection().fromPixels(centerPoint.x + getHeight()/4, centerPoint.y);
		animateTo(newCenterGeoPoint);
	}
	
	@Override
	public int zoomIn(){
		if(!getController().zoomIn()){ 
			soundManager.playSound(SoundManagerCostants.ZOOM_LIMIT_REACHED);
		}
		return getZoomLevel();
	}
	
	@Override
	public int zoomOut(){
		if(!getController().zoomOut()){ 
			soundManager.playSound(SoundManagerCostants.ZOOM_LIMIT_REACHED);
		}
		return getZoomLevel();
	}
	
	@Override
	public int setZoomLevel(int zoomLevel){
		return getController().setZoom(zoomLevel);
	}
	
	@Override
	public boolean onTouchEvent(MotionEvent event){
		super.onTouchEvent(event);
			// TODO Auto-generated method stub
		if(!eventHandled){	
			gestureDetector.onTouchEvent(event);
		}
		eventHandled = false;
		return true;
	}
	
	@Override
	public boolean onDoubleTap(MotionEvent event) {
		// TODO Auto-generated method stub
		GeoPoint p = getProjection().fromPixels((int)event.getX(), (int)event.getY());
		animateTo(p);
		zoomIn();
		return true;
	}

	@Override
	public boolean onDoubleTapEvent(MotionEvent arg0) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean onSingleTapConfirmed(MotionEvent e) {
		// TODO Auto-generated method stub
		if(isStreetView()){
			Vibrator vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
			vibrator.vibrate(75);
			
			int x = (int) e.getX();
			int y = (int) e.getY();
			
			GeoPoint geoPoint = getProjection().fromPixels(x, y);
			
			Intent streetViewIntent = new Intent(Intent.ACTION_VIEW);
			streetViewIntent.setData(Uri.parse("google.streetview:cbll=" + 
					geoPoint.getLatitudeE6()/1E6 + 
					"," + 
					geoPoint.getLongitudeE6()/1E6 + 
					"&cbp=1,0,,0,1.0&mz=1"));
			context.startActivity(streetViewIntent);
			return true;
		}
		return false;
	}

	@Override
	public boolean onDown(MotionEvent e) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
			float velocityY) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public void onLongPress(MotionEvent e) {
		// TODO Auto-generated method stub
		Vibrator vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
		vibrator.vibrate(75);
		
		int x = (int) e.getX();
		int y = (int) e.getY();
		
		GeoPoint point = getProjection().fromPixels(x, y);
		try {
			String result = SearchAddressView.getAddressString(context, point);
			if(!result.contentEquals("")) 
				Toast.makeText(context, result, Toast.LENGTH_SHORT).show();
			else
				soundManager.playSound(SoundManagerCostants.ZOOM_LIMIT_REACHED);
		} catch (IOException e1) {
			// TODO Auto-generated catch block
			Toast.makeText(context, context.getString(R.string.internet_off), Toast.LENGTH_SHORT).show();
		} catch (IllegalArgumentException e2){
			e2.printStackTrace();
		}
		
	}

	@Override
	public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
			float distanceY) {
		// TODO Auto-generated method stub
		return false;
	}

	@Override
	public void onShowPress(MotionEvent e) {
		// TODO Auto-generated method stub
	}

	@Override
	public boolean onSingleTapUp(MotionEvent e) {
		// TODO Auto-generated method stub
		return false;
	}

	public void setLastMarkerTapped(int lastMarkerTapped, int overlayId) {
		this.lastMarkerTapped = lastMarkerTapped;
		this.lastOverlayTapped = overlayId;
	}

	public int getLastMarkerTapped() {
		return lastMarkerTapped;
	}
	
	public int getLastOverlayTapped(){
		return this.lastOverlayTapped;
	}
	
	public static Location fromGeoPointToLocation(GeoPoint p){
		Location l = new Location(LocationManager.GPS_PROVIDER);
		l.setLatitude(p.getLatitudeE6() / 1E6);
		l.setLongitude(p.getLongitudeE6() / 1E6);
		return l;
	}
	
	public static GeoPoint fromLocationToGeoPoint(Location l){
		int latE6 = (int) (l.getLatitude()*1E6);
		int lonE6 = (int) (l.getLongitude()*1E6);
		return new GeoPoint(latE6, lonE6);
	}
	
}
